home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Graphics 2D / CalcCMask CalcMask / CalcMask.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-09-28  |  10.3 KB  |  332 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        CalcCMask & CalcMask.c
  3.  
  4.     Contains:    This snippet shows how to use both CalcCMask or                
  5.                 CalcMask to create a mask given a source bitmap                
  6.                 image.  As decribed on pages IV-24 and V-72 of                
  7.                 Inside Mac, the two routines compute a destination                
  8.                 bitmap image with 1's only in the pixels where                
  9.                 paint can not leak from any of the outer edges.            
  10.                 This is similar to the lasso tool found in many                
  11.                 drawing apps.                    
  12.  
  13.     Written by: EL    
  14.  
  15.     Copyright:    Copyright © 1992-1999 by Apple Computer, Inc., All Rights Reserved.
  16.  
  17.                 You may incorporate this Apple sample source code into your program(s) without
  18.                 restriction. This Apple sample source code has been provided "AS IS" and the
  19.                 responsibility for its operation is yours. You are not permitted to redistribute
  20.                 this Apple sample source code as "Apple sample source code" after having made
  21.                 changes. If you're going to re-distribute the source, we require that you make
  22.                 it clear in the source that the code was descended from Apple sample source
  23.                 code, but that you've made changes.
  24.  
  25.     Change History (most recent first):
  26.                 08/2000        JM                Carbonized, non-Carbon code is commented out
  27.                                             for demonstration purposes.
  28.                 7/8/1999    KG                Updated for Metrowerks Codewarror Pro 2.1
  29.                 
  30.  
  31. */
  32. #include "CarbonPrefix.h"
  33. #include <Dialogs.h>
  34. #include <Fonts.h>
  35. #include <QDOffscreen.h>
  36. #include <Resources.h>
  37. /* Constant Declarations */
  38.  
  39. #define    WWIDTH        176
  40. #define    WHEIGHT        106
  41.  
  42. //#define WLEFT        (((qd.screenBits.bounds.right - qd.screenBits.bounds.left) - WWIDTH) / 2)
  43. //#define WTOP        (((qd.screenBits.bounds.bottom - qd.screenBits.bounds.top) - WHEIGHT) / 2)
  44.  
  45. /* Global Variable Definitions */
  46.  
  47. WindowPtr    gWindow;
  48.  
  49. void initMac();
  50. void createWindow();
  51. void doCalcCMaskExample();
  52.  
  53. void DisposeGrafPort(GrafPtr ptr);
  54. GrafPtr CreateGrafPort(Rect *rect);
  55.  
  56. void doEventLoop();
  57.  
  58. void main(void)
  59. {
  60.     initMac();
  61.     
  62.     createWindow();
  63.     
  64.     doEventLoop();
  65. }
  66.  
  67. void initMac()
  68. {
  69.     /*MaxApplZone();
  70.     
  71.     InitGraf( &qd.thePort );
  72.     InitFonts();
  73.     InitWindows();
  74.     InitMenus();
  75.     TEInit();
  76.     InitDialogs( nil );*/
  77.     InitCursor();
  78.     FlushEvents( 0, everyEvent );
  79. }
  80.  
  81. void createWindow()
  82. {
  83.     Rect rect;
  84.     BitMap    bitMap;
  85.     int    top, left;
  86.     
  87.     GetQDGlobalsScreenBits(&bitMap);
  88.     
  89.     left = (((bitMap.bounds.right - bitMap.bounds.left) - WWIDTH) / 2);
  90.     top = (((bitMap.bounds.bottom - bitMap.bounds.top) - WHEIGHT) / 2);
  91.     
  92.     //SetRect( &rect, WLEFT, WTOP, WLEFT + WWIDTH, WTOP + WHEIGHT );
  93.     SetRect( &rect, left, top, left + WWIDTH, top + WHEIGHT );
  94.     
  95.     gWindow = NewCWindow( 0L, &rect, "\pCalc-C-Mask", true, documentProc,
  96.                             (WindowPtr)-1L, true, 0L );
  97.                             
  98.     //SetPort( gWindow );
  99.     SetPortWindowPort( gWindow );
  100. }
  101.  
  102. #define COLOR_VERSION
  103.  
  104. void doCalcCMaskExample()
  105. {
  106.     PicHandle    pict;                /* B/W Pict used to create mask. */
  107.     GWorldPtr    gworld;                /* Gworld used for CopyMask source. */
  108.     //GrafPtr     mask;                /* Mask created by CalcCMask. */
  109.     GrafPtr        sourceForMask;        /* Bitmap of pict image used for creating mask. */
  110.     GrafPtr        oldPort;            // Old port, saved then restored
  111.     RGBColor    seedColor;            /* Color used to determine the mask. */
  112.     Rect        rect;                /* Bounding rect of mask and source. */
  113.     CGrafPtr    currentPort;        /* Saved CGrafPtr for later restore. */
  114.     GDHandle    currentDevice;        /* Saved device for later restore. */
  115.     Rect        tempRect1, tempRect2; // Used for carbonization
  116.     OSErr        err = noErr;
  117.     GWorldPtr    newMask;
  118.     
  119.     GetPort(&oldPort);
  120.     
  121.     /* Load the pict resource to be used for the mask. */
  122.     pict = (PicHandle)GetResource( 'PICT', 128 );
  123.     
  124.     /* Define the bounding rect for the source and mask bitmap. */
  125.     rect = (**pict).picFrame;
  126.     OffsetRect( &rect, -rect.left, -rect.top );
  127.     
  128.     /* Allocate the source bitmap for which the mask will be created from. */
  129.     sourceForMask = CreateGrafPort( &rect );
  130.     
  131.     /* Create the source bitmap's image by using the pict. */
  132.     SetPort( sourceForMask );
  133.     DrawPicture( pict, &rect );
  134.     //SetPort( gWindow );
  135.     SetPortWindowPort( gWindow );
  136.     
  137.     /* Release the memory used by the pict. */
  138.     ReleaseResource( (Handle)pict );
  139.     
  140.     /* Copy the source image to the window to see what the mask was created from. */
  141.     /*CopyBits( &sourceForMask->portBits, &gWindow->portBits,
  142.                 &sourceForMask->portRect, &rect, srcCopy, nil );*/
  143.     CopyBits(GetPortBitMapForCopyBits(sourceForMask), GetPortBitMapForCopyBits(GetWindowPort(gWindow)),
  144.             GetPortBounds(sourceForMask, &tempRect1), &rect, srcCopy, nil );
  145.     
  146.     /* Allocate the bitmap for the mask. */
  147.     //mask = CreateGrafPort( &sourceForMask->portRect );
  148.     GetGWorld( ¤tPort, ¤tDevice );
  149.     NewGWorld(&newMask, 1, GetPortBounds(sourceForMask, &tempRect1), nil, nil, 0);
  150.     SetGWorld( newMask, nil );
  151.     EraseRect( &tempRect1 );
  152.     
  153.     GetPortBounds(sourceForMask, &tempRect1);
  154.     GetPortBounds(newMask, &tempRect2);
  155.     LockPixels(GetPortPixMap(sourceForMask));
  156.     LockPixels(GetGWorldPixMap(newMask));
  157.  
  158. #ifdef COLOR_VERSION
  159.     /* Create a mask from the source bitmap of all colors that match the seedColor. */
  160.     seedColor.red = seedColor.green = seedColor.blue = 0;
  161.     
  162.     /*CalcCMask( &sourceForMask->portBits, &mask->portBits, &sourceForMask->portRect,
  163.                 &mask->portRect, &seedColor, nil, 0 );*/
  164.  
  165.     CalcCMask( (BitMap *) *(GetPortPixMap(sourceForMask)), (BitMap *)*(GetPortPixMap(newMask)), &tempRect1, &tempRect2,
  166.      &seedColor, nil, 0);
  167.  
  168. #else
  169.  
  170.     /*CalcMask( &sourceForMask->portBits.baseAddr, &mask->portBits.baseAddr,
  171.                 sourceForMask->portBits.rowBytes, mask->portBits.rowBytes,
  172.                 sourceForMask->portRect.bottom - sourceForMask->portRect.top,
  173.                 sourceForMask->portBits.rowBytes >> 1 );*/
  174.     // This is not recommended since the ports are all color ports under Carbon
  175.     GetPortBounds(sourceForMask, &tempRect1);
  176.     CalcMask( (*(GetPortPixMap(sourceForMask)))->baseAddr, (*(GetGWorldPixMap(newMask)))->baseAddr,
  177.                 (*(GetPortPixMap(sourceForMask)))->rowBytes, (*(GetPortPixMap(newMask)))->rowBytes,
  178.                 tempRect1.bottom - tempRect1.top, (*(GetPortPixMap(sourceForMask)))->rowBytes >> 1);
  179. #endif
  180.  
  181.     
  182.     UnlockPixels(GetPortPixMap(sourceForMask));
  183.     UnlockPixels(GetPortPixMap(newMask));
  184.     SetGWorld( currentPort, currentDevice );
  185.     
  186.     // Create a gworld of a blue rectangle for the CopyMask source.
  187.     //GetGWorld( ¤tPort, ¤tDevice );
  188.     err = NewGWorld( &gworld, 8, &rect, nil, nil, 0 );
  189.     //SetPort( (GrafPtr)gworld );
  190.     SetGWorld( gworld, nil );
  191.     ForeColor( blueColor );
  192.     PaintRect( &rect );
  193.     SetGWorld( currentPort, currentDevice );
  194.     
  195.     // Now draw the blue rectangle with its mask. 
  196.     //OffsetRect( &rect, sourceForMask->portRect.right, 0 );
  197.     OffsetRect( &rect, GetPortBounds(sourceForMask, &tempRect1)->right, 0 );
  198.     //CopyMask( (BitMap*)&(*gworld).portPixMap, &mask->portBits, &gWindow->portBits,
  199.     //            &sourceForMask->portRect, &mask->portRect, &rect );
  200.     //SetPortWindowPort(gWindow);
  201.     GetGWorld( ¤tPort, ¤tDevice );
  202.     SetGWorld(GetWindowPort(gWindow), nil);
  203.     LockPixels(GetPortPixMap(gworld));
  204.     LockPixels(GetPortPixMap(newMask));
  205.     CopyMask( (BitMap*)*(GetPortPixMap(gworld)), (BitMap *)*(GetPortPixMap(newMask)), GetPortBitMapForCopyBits(GetWindowPort(gWindow)),
  206.                 GetPortBounds(sourceForMask, &tempRect1), GetPortBounds(newMask, &tempRect2), &rect );
  207.     UnlockPixels(GetPortPixMap(gworld));
  208.     UnlockPixels(GetGWorldPixMap(newMask));
  209.  
  210.     // Release the used memory. 
  211.     DisposeGrafPort( sourceForMask );
  212.     //DisposeGrafPort( mask );
  213.     DisposeGWorld( newMask );
  214.     DisposeGWorld( gworld );
  215.     SetPort( oldPort );
  216. }
  217.  
  218. GrafPtr CreateGrafPort( Rect *bounds )    /* CreateGrafPort originally written by Forrest Tanaka. */
  219. {
  220.     GrafPtr    savedPort;        /* Saved GrafPtr for later restore. */
  221.     GrafPtr    newPort;        /* New GrafPort. */
  222.     Rect    localBounds;    /* Local copy of bounds. */
  223.     RgnHandle        rgnHandle = NewRgn();    // Used for carbonization
  224.  
  225.     GetPort( &savedPort );
  226.  
  227.     /* Set the top-left corner of bounds to (0,0). */
  228.     localBounds = *bounds;
  229.     OffsetRect( &localBounds, -bounds->left, -bounds->top );
  230.  
  231.     /* Allocate a new GrafPort. */
  232.     //newPort = (GrafPtr)NewPtrClear( sizeof( GrafPort ) );
  233.     newPort = CreateNewPort();
  234.     
  235.     if (newPort != nil)
  236.     {
  237.         /* Initialize the new port and make the current port. */
  238.         //OpenPort( newPort );
  239.         SetPort( newPort);
  240.  
  241.         /* Initialize and allocate the bitmap. */
  242.         /*newPort->portBits.bounds = localBounds;
  243.           newPort->portBits.rowBytes = ((localBounds.right + 15) >> 4) << 1;
  244.         newPort->portBits.baseAddr =  NewPtrClear( newPort->portBits.rowBytes *
  245.                                                     (long)localBounds.bottom );*/
  246.         
  247.         LockPixels(GetPortPixMap(newPort));    
  248.         
  249.         (*(GetPortPixMap(newPort)))->bounds = localBounds;
  250.         (*(GetPortPixMap(newPort)))->rowBytes = ((localBounds.right + 15) >> 4) <<1;
  251.         (*(GetPortPixMap(newPort)))->baseAddr = NewPtrClear((*(GetPortPixMap(newPort)))->rowBytes *
  252.                                                         (long)localBounds.bottom );
  253.  
  254.         UnlockPixels(GetPortPixMap(newPort));
  255.         
  256.         //if (newPort->portBits.baseAddr != nil)
  257.         if (GetPortBitMapForCopyBits(newPort)->baseAddr != nil)
  258.         {
  259.             /* Clean up the new port. */
  260.             //newPort->portRect = localBounds;
  261.             SetPortBounds(newPort, &localBounds);
  262.             ClipRect( &localBounds );
  263.             //RectRgn( newPort->visRgn, &localBounds );
  264.             RectRgn( GetPortVisibleRegion(newPort, rgnHandle), &localBounds );
  265.             EraseRect( &localBounds );
  266.         }
  267.         else
  268.         {
  269.             /* Allocation failed; deallocate the port. */
  270.             /*ClosePort( newPort );
  271.             DisposePtr( (Ptr)newPort );*/
  272.             DisposePort( newPort );
  273.             newPort = nil;
  274.         }
  275.     }
  276.     
  277.     DisposeRgn(rgnHandle);
  278.     SetPort( savedPort );
  279.     return newPort;
  280. }
  281.  
  282. void DisposeGrafPort( GrafPtr doomedPort )    /* DisposeGrafPort originally written by Forrest Tanaka. */
  283. {
  284.     //ClosePort( doomedPort );
  285.     //DisposePtr( doomedPort->portBits.baseAddr );
  286.     DisposePtr( GetPortBitMapForCopyBits(doomedPort)->baseAddr );
  287.     //DisposePtr( (Ptr)doomedPort );
  288.     DisposePort( doomedPort );
  289. }
  290. void doEventLoop()
  291. {
  292.     EventRecord event;
  293.     WindowPtr   window;
  294.     short       clickArea;
  295.     Rect        screenRect;
  296.  
  297.     for (;;)
  298.     {
  299.         if (WaitNextEvent( everyEvent, &event, 0, nil ))
  300.         {
  301.             if (event.what == mouseDown)
  302.             {
  303.                 clickArea = FindWindow( event.where, &window );
  304.                 
  305.                 if (clickArea == inDrag)
  306.                 {
  307.                     //screenRect = (**GetGrayRgn()).rgnBBox;
  308.                     GetRegionBounds(GetGrayRgn(), &screenRect);
  309.                     DragWindow( window, event.where, &screenRect );
  310.                 }
  311.                 else if (clickArea == inContent)
  312.                 {
  313.                     if (window != FrontWindow())
  314.                         SelectWindow( window );
  315.                 }
  316.                 else if (clickArea == inGoAway)
  317.                     if (TrackGoAway( window, event.where ))
  318.                         return;
  319.             }
  320.             else if (event.what == updateEvt)
  321.             {
  322.                 window = (WindowPtr)event.message;    
  323.                 //SetPort( window );
  324.                 SetPortWindowPort( window );
  325.                 
  326.                 BeginUpdate( window );
  327.                 doCalcCMaskExample();
  328.                 EndUpdate( window );
  329.             }
  330.         }
  331.     }
  332. }